package logica;


import grafica.ControlGraficos;
import java.awt.Color;

import logica.coleccionables.Coleccionable;
import logica.pisos.Piso;
import logica.robots.*;

/**
 * Esta clase administra toda la lógica del juego. 
 * 
 * @author Amorosi, Javier (94528)
 * @author Antiman, Nehuen (102440)
 */
public class ControlJuego {
	
	private ControlGraficos g;
	
	private Robot robot;	
	private IniciarNivel inicio;	
	private Nivel nivel;	
	private String nivelInicial;	
	
	private Piso pisoActual;
	
	/**
	 * Constructor de control juegos. 
	 *
	 * @param c control de gráficos asociado al control lógico.
	 */
	public ControlJuego(ControlGraficos c) {
		g=c;		
	}
	
	private void seleccionarRobot(int r) {
		if(r==0)
			robot=new RobotCivil();
		else if (r==1)
			robot = new RobotMilitar();
	}
	
	/**
	 * Se inicializa el nivel seguún _nivelInicial, en caso de ser nulo
	 * se carga un nivel por defecto. 
	 * Un nivel válido es aquel generado con la aplicación "Editor de Niveles".
	 * 
	 * Tipos de Robot:
	 * 0 robot civil.
	 * 1 robot militar.
	 * 
	 * @param _nivelInicial nivel a cargar.
	 * @param r indica el tipo de robot que se eligio. 
	 */
	public void iniciarNivel(String _nivelInicial, int r) {
		
		seleccionarRobot(r);
		inicio=new IniciarNivel();
		nivel=new Nivel(12, 16);
		if (_nivelInicial==null)
			nivelInicial= new String(
				"G;G;G;G;G;G;G;G;G;G;G;G;G;G;G;G;\n"+
				"G;G;R;RB;RZ;RC;RT;R;R;R;R;R#;RE;RP;G;G;\n"+
				"G;R;R;RB;RT;RT;RT;R;R;R;RE;RE;RE;R;R;G;\n"+
				"RP;R;R;R;R;R;RO;R;R;R;R;R;R;R;R;R;\n"+
				"RL;R;RL;R;RL;R;RL;R;RL;R;RL;R;RL;R;RL;RC;\n"+
				"A;A;A;A;A;A;A;A;AB;A;A;A;A;A;A;A;\n"+
				"A;A;A;A;A;A;A;A;A;A;A;A;A;A;A;A;\n"+
				"RP;R;RT;RT;RT;R;R;A;A;R;RT;RT;RJ;R;R;R;\n"+
				"R;R;R;RT;R;R;R;A;A;R;RT;RT;R;RT;RT;RT;\n"+
				"R;R;R;R;R;R;R;A;A;R;R;R;RO;RT;G;RT;\n"+
				"R;R;R;R@;R;RC;R;A;A;R;R;R;R;RT;RT;RT;\n"+
				"A;A;A;A;A;A;A;A;A;A;A;A;A;A;A;AB;\n");
		else
			nivelInicial=_nivelInicial;
		
		inicio.iniciar(nivelInicial, nivel, g, r);
		pisoActual=nivel.getPisoInicial(); 
	}
	
	/**
	 * Le da fin al juego. 
	 */
	private void finalizarNivel(boolean win) {
		if (win)
			g.exito();
		else
			g.fracaso();
	}
	
	/**
	 * Se le requiere al robot lógico que avanze.
	 * @return true si el robot en efecto avanzó, false caso contrario. 
	 */
	public boolean avanzarRobot() {
		boolean r=false;
		if(robot.avanzar(pisoActual.consumoCombustible())){
			Piso aux = proximoPiso();
			if ( aux != null && aux.puedoPasar()){
				actualizarPiso(aux);
				if (!nivel.esPisoFinal(pisoActual)){
					r=true;
					if (aux.tienePremio())
						robot.recolectarPremio(pisoActual.proveerPremio());
				}else
					finalizarNivel(true);
			}
		}
		else
			finalizarNivel(false);
		return r;
	}
	
	/**
	 * Se le requiere al robot lógico que gire.
	 * @return true si el robot en efecto giró, false caso contrario. 
	 */
	public boolean girarRobot(int orientacion) {
		boolean r=robot.girar(orientacion, pisoActual.consumoCombustible());
		if (!r)
			finalizarNivel(false);
		return r;
	}
	
	/**
	 * Se le requiere al robot lógico que realize su accion especial.
	 * El robot civil no posee alguna, el robot militar dispara a distancia. 
	 * @return true si el robot en efecto avanzó, false caso contrario. 
	 */
	public boolean accionEspecial() {		
		boolean r=robot.accionEspecial(nivel, pisoActual);						
		return r;
	}
	
	public void activarPincel(Color color) {
		robot.activarPincel(color);
	}
	
	public void desactivarPincel() {
		robot.desactivarPincel();
	}
	
	/**
	 * El robot recoge un coleccionable (si hay alguno) desde su celda trasera.
	 * @return true si habia un coleccionable, false caso contrario.
	 */
	public boolean recogerColeccionable() {
		boolean r=false;
		Piso aux = celdaTrasera();
		if (aux != null){
			r=aux.tieneColeccionable();
			if (r)
				robot.recolectarColeecionable(aux.proveerColeccionable());
		}
		return r;
	}
	
	/**
	 * El robot suelta un coleccionable (si puede) en su celda trasera.
	 * @return true si pudo soltar un coleccionable, false caso contrario.
	 */
	public boolean soltarColeccionable() {
		boolean r=false;		
		Piso trasero=celdaTrasera();
		if (trasero!=null)
			if (!trasero.tieneAlgo()){
				Coleccionable coleccionable=robot.soltarColeccionable();
				if (coleccionable!=null){
					trasero.colocarColeccionable(coleccionable);
					r=true;
				}
			}
		return r;
	}
		
	private void actualizarPiso(Piso c) {
		pisoActual =c;
	}
	
	private Piso proximoPiso() {
		int f=pisoActual.getFila();
		int c = pisoActual.getColumna();
		int o = robot.getOrientacion();
		switch(o){
			case Orientacion.ARRIBA : f--;
			break;
			case Orientacion.DERECHA : c++;
			break;
			case Orientacion.ABAJO : f++;
			break;
			case Orientacion.IZQUIERDA : c--;
			break;
		}
		Piso toR =null;
		if (nivel.estaEnRango(f, c))
			toR = nivel.getPiso(f, c);
		return toR;
	}
	
	private Piso celdaTrasera() {
		int f=pisoActual.getFila();
		int c = pisoActual.getColumna();
		int o = robot.getOrientacion();
		switch(o){
			case Orientacion.ARRIBA : f++;
			break;
			case Orientacion.DERECHA : c--;
			break;
			case Orientacion.ABAJO : f--;
			break;
			case Orientacion.IZQUIERDA : c++;
			break;
		}
		Piso toR =null;
		if (nivel.estaEnRango(f, c))
			toR = nivel.getPiso(f, c);
		return toR;
	}
	
	/**
	 * Retorna la orientacion del robot. 
	 * @return orientacion del robot.
	 */
	public int getOrientacionRobot(){
		return robot.getOrientacion();
	}
	
	/**
	 * Retorna un String con la posicion del robot y sus atributos.  
	 */
	public String toString(){
		String s=new String(
				"Posicion: Fila "+pisoActual.getFila()+", Columna "+pisoActual.getColumna()+" | "+		
				robot.toString());
		return s;
	}
}
